import 'package:flutter/foundation.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:photo_frame/net/http_manager.dart';
import 'package:photo_frame/net/model/member_model.dart';
import 'package:photo_frame/utils/a_logger.dart';
import 'package:photo_frame/utils/localization_util.dart';
import 'package:provider/provider.dart';
import 'package:sqflite/sqflite.dart';

UsersViewModel _usersViewModel = UsersViewModel();

class UsersProvider extends ChangeNotifierProvider<UsersViewModel> {
  UsersProvider.value() : super.value(value: _usersViewModel);
}

class UsersViewModel extends ChangeNotifier {
  static late UserDBHelper _dbHelper;

  List<MemberModel>? _members;

  List<MemberModel>? get members => _members;

  static init() async {
    _dbHelper = UserDBHelper();
    await _dbHelper.init();
    if (kDebugMode) {
      // _dbHelper.deleteAll();
    }
  }

  Future<void> fetch(String frameId, {bool? notify = true}) async {
    return HttpManager.instance.doRequest("/info/getframeuser", parameters: {
      'frame_id': frameId,
    }).then((e) async {
      if (e.isSuccess) {
        await _dbHelper.deleteAll();
        final List<MemberModel> memList = [];
        memList.addAll((e.data['accounts'] as List<dynamic>?)?.map((e) {
              var map = Map<String, dynamic>.of(e)
                ..['frame_id'] = frameId
                ..['isActive'] = 1;
              return MemberModel.fromMap(map);
            }).toList() ??
            []);
        memList.addAll((e.data['roles'] as List<dynamic>?)?.map((e) {
              var map = Map<String, dynamic>.of(e)
                ..['frame_id'] = frameId
                ..['isActive'] = 0;
              return MemberModel.fromMap(map);
            }).toList() ??
            []);
        ALogger.e("user-fetch : ${memList.map((e) => e.frame_id)}");

        await Future.wait(memList.map((e) => _dbHelper.insert(e)))
            .catchError((e) {
          ALogger.e(e);
        });
        await _onDataSetChanged(notify: notify);
      }
    }).catchError((e) {
      Fluttertoast.showToast(
          msg:
              e.msg ?? AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
    });
  }

  Future<bool> add(String frameId, MemberModel memberModel) {
    return HttpManager.instance
        .doRequest("/info/addattendee",
            parameters: memberModel.toMap()..['frame_id'] = frameId)
        .then((e) async {
      if (e.isSuccess) {
        var memberEntity = MemberModel.fromMap(e.data);
        memberEntity.frame_id = frameId;
        _dbHelper.insert(memberEntity);
        _onDataSetChanged();
        Fluttertoast.showToast(
            msg: AppLocalizationsWrapper.instance
                .unwrapNoCtx()
                .createSuccessful);
        return true;
      }
      Fluttertoast.showToast(
          msg:
              e.msg ?? AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
      return false;
    }).catchError((e) {
      Fluttertoast.showToast(
          msg: AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
      return false;
    });
  }

  Future<bool> update(String frameId, MemberModel memberModel) {
    return HttpManager.instance
        .doRequest("/api/updateuser", parameters: memberModel.toMap())
        .then((e) async {
      if (e.isSuccess) {
        _dbHelper.update(memberModel);
        _onDataSetChanged();
        Fluttertoast.showToast(
            msg: AppLocalizationsWrapper.instance
                .unwrapNoCtx()
                .memberEditSuccessful);
        return true;
      }
      Fluttertoast.showToast(
          msg:
              e.msg ?? AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
      return false;
    }).catchError((e) {
      Fluttertoast.showToast(
          msg: AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
      return false;
    });
  }

  Future<void> delete(num id) {
    return HttpManager.instance.doRequest("/api/deluser", parameters: {
      "id": id,
    }).then((e) async {
      if (!e.isSuccess) {
        Fluttertoast.showToast(
            msg: e.msg ??
                AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
        return;
      }
      _dbHelper.delete(id);
      _onDataSetChanged();
    }).catchError((e) {
      print(e);
      Fluttertoast.showToast(
          msg: AppLocalizationsWrapper.instance.unwrapNoCtx().netError);
    });
  }

  _onDataSetChanged({bool? notify = true}) async {
    _members = await _dbHelper.queryAll();
    ALogger.e("_onDataSetChanged  : ${_members?.length ?? 0}");
    if (notify == true) {
      notifyListeners();
    }
  }
}

class UserDBHelper {
  final String tableEvents = 'users';
  late Database _db;

  init() async {
    _db =
        await openDatabase("$tableEvents.db", version: 1, onCreate: _onCreate);
  }

  Future<void> _onCreate(Database db, int version) async {
    await db.execute('''
      CREATE TABLE $tableEvents (
        autoId integer PRIMARY KEY AUTOINCREMENT, 
        id integer UNIQUE,
        frame_id text,
        email text,
        name text ,
        color integer,
        isActive integer
        )
    ''');
  }

  Future<List<MemberModel>> queryAll() async {
    return await _db.query(tableEvents).then((e) {
      return e.map((e) => MemberModel.fromMap(e)).toList();
    });
  }

  Future<int> insert(MemberModel dto) async {
    ALogger.e("insert enter: $dto");
    return await _db.insert(tableEvents, dto.toMap(),
        conflictAlgorithm: ConflictAlgorithm.replace);
  }

  Future<MemberModel?> getById(int id) async {
    List<Map<String, dynamic>> maps = await _db.query(tableEvents,
        columns: ['id'], where: 'id = ?', whereArgs: [id]);
    if (maps.isNotEmpty) {
      return MemberModel.fromMap(maps.first);
    }
    return null;
  }

  Future<int> delete(num id) async {
    return await _db.delete(tableEvents, where: 'id = ?', whereArgs: [id]);
  }

  Future<int> deleteAll() async {
    return await _db.delete(tableEvents);
  }

  Future<int> update(MemberModel dto) async {
    return _db.update(
      tableEvents,
      dto.toMap(),
      where: 'id = ? ',
      whereArgs: [dto.id],
    );
  }
}

extension MemberListFilter on List<MemberModel>? {
  List<MemberModel> filterByFrameId(String? frameId) {
    ALogger.e("filterByFrameId : ${this?.map((e) => e.frame_id)}");
    if (this == null) return [];
    return this!.where((member) => member.frame_id == frameId).toList();
  }
}
